`timescale 1ns / 1ps

`include "macro.vh"

module alu(
	input clk,
	input rst,

	input [3:0] oper,
	input [31:0] num1,
	input [31:0] num2,
	output [31:0] res,
	output err
    );

	// result lines
	wire [31:0] add_result;
	wire [31:0] sub_result;
	wire [31:0] and_result;
	wire [31:0] or_result;
	wire [31:0] slt_result;
	wire [31:0] sll_result;

	assign add_result = num1 + num2;
	assign sub_result = num1 - num2;
	assign and_result = num1 & num2;
	assign or_result = num1 | num2;
	assign slt_result = (num1 < num2) ? 32'b1:32'b0;
	assign sll_result = num1 << num2[4:0];

	// error 
	reg alu_err;

	always @(*) begin
		if(!rst) begin
			alu_err <= 0;
		end else if (oper == `ALU_ADD && add_result[32] != add_result[31]) begin
			alu_err <= 1;
		end	else if (oper == `ALU_SUB && sub_result[32] != sub_result[31]) begin
			alu_err <= 1;
		end	else begin
			alu_err <= 0;
		end
	end

	assign err = alu_err;

	// result
	assign res = (oper == `ALU_ADD) ? add_result :
				(oper == `ALU_SUB)  ? sub_result :
				oper == `ALU_AND  ? and_result :
				oper == `ALU_OR   ? or_result :
				oper == `ALU_SLT  ? slt_result :
				oper == `ALU_SLL  ? sll_result : 
				oper == `ALU_NULL ? num1 : 32'b0;

endmodule
